#[macro_export]
macro_rules! cstr {
    ($s:expr) => {
        $s.as_ptr() as *const core::ffi::c_char
    };
}

#[macro_export]
macro_rules! try_io_err {
    ($stat:expr, $err_str:expr) => {
        let ret = $stat;
        if ret != 0 {
            return Err($crate::Error::Io(ret, $err_str));
        }
    };
}

#[macro_export]
macro_rules! cstr_ptr {
    ($rstr:expr) => {
        concat!($rstr, "\0").as_ptr() as *const core::ffi::c_char
    };
}

#[macro_export]
macro_rules! capi {
    ( $func_name:ident($($arg:tt)*), $fname:expr) => {
        {
            let ret = unsafe { $func_name($($arg)*) };
            if 0 != ret {
                $crate::errorln!("{} failed: 0x[{:x}]", $fname, ret);
                return ret;
            }
            ret
        }
    };
    ( $expr:expr, $fname:expr) => {
        {
            let ret = unsafe{ $expr };
            if 0 != ret {
                $crate::errorln!("{} failed: 0x[{:x}]", $fname, ret);
                return ret;
            }
            ret
        }
    };
}

#[macro_export]
macro_rules! capi_r {
    ( $func_name:ident($($arg:tt)*), $fname:expr) => {
        {
            let ret = unsafe { $func_name($($arg)*) };
            if 0 != ret {
                $crate::errorln!("{} failed: [0x{:x}]", $fname, ret);
                return Err($crate::Error::ApiRef(ret, $fname));
            }
        }
    };
    ( $expr:expr, $fname:expr) => {
        {
            let ret = unsafe{ $expr };
            if 0 != ret {
                $crate::errorln!("{} failed: [0x{:x}]", $fname, ret);
                return Err($crate::Error::ApiRef(ret, $fname));
            }
        }
    };
}

#[macro_export]
macro_rules! capi_r1 {
    ( $func_name:ident($($arg:tt)*), $fname:expr) => {
        {
            let ret = unsafe { $func_name($($arg)*) };
            if 0 != ret {
                $crate::errorln!("{} failed: [{}]", $fname, ret);
                return Err($crate::Error::ApiRef(ret, $fname));
            }
        }
    };
    ( $expr:expr, $fname:expr) => {
        {
            let ret = unsafe{ $expr };
            if 0 != ret {
                $crate::errorln!("{} failed: [{}]", $fname, ret);
                return Err($crate::Error::ApiRef(ret, $fname));
            }
        }
    };
}

#[macro_export]
macro_rules! capi_err_log {
    ( $func_name:ident($($arg:tt)*), $fname:expr) => {
        {
            let ret = unsafe { $func_name($($arg)*) };
            if 0 != ret {
                $crate::errorln!("{} failed: [0x{:x}]", $fname, ret);
            }
        }
    };
    ( $expr:expr, $fname:expr) => {
        {
            let ret = unsafe{ $expr };
            if 0 != ret {
                $crate::errorln!("{} failed: [0x{:x}]", $fname, ret);
            }
        }
    };
}

#[macro_export]
macro_rules! log_err {
    ( $func_name:ident($($arg:tt)*), $fname:expr) => {
        if let Err(e) = $func_name($($arg)*) {
            $crate::errorln!("{} failed: {}", $fname, e.to_string());
        }
    };
    ( $expr:expr, $fname:expr) => {
        if let Err(e) = $expr {
            $crate::errorln!("{} failed: {}", $fname, e.to_string());
        }
    };
}

#[macro_export]
macro_rules! triple_op {
    ( $cond:expr, $true_v:expr, $false_v:expr) => {
        if $cond {
            $true_v
        } else {
            $false_v
        }
    };
}

#[macro_export]
macro_rules! to_slice {
    ( $data_ref:expr, $data_type:tt) => {{
        unsafe {
            std::slice::from_raw_parts(
                $data_ref as *const $data_type as *const u8,
                std::mem::size_of_val($data_ref),
            )
        }
    }};
}

#[macro_export]
macro_rules! to_slice_mut {
    ( $data_ref:expr, $data_type:tt) => {{
        unsafe {
            std::slice::from_raw_parts_mut(
                $data_ref as *mut $data_type as *mut u8,
                std::mem::size_of_val($data_ref),
            )
        }
    }};
}
